#include "prj1u.h"
#include "GuiFrontPanel.h"
#include "common_typedef.h"

#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdarg.h>
#include <pthread.h>
#include "SysCall.h"

static lv_obj_t * g_labelTopLeft;
static lv_obj_t * g_labelBottomLeft;
static lv_obj_t * g_btnWorkShopPwr;
static char g_stateBarStr[128] = {0};
pthread_mutex_t g_uiMutex;

static char strbuff[256];
#define LCD_V_RES 320
#define LCD_H_RES 240
#define DISP_BUF_SIZE (128 * 1024)

void lv_drv_init();
void InitBackGround();
void InitLabelTopLeft();
void InitLabelBottomLeft();
void InitBtnWorkshopPwr();

/* 外部导出方法 */
int GuiFrontPanelMain(void)
{
    printf("[%s] enter\n", APP_GUIFRONTPANEL);
    /*LittlevGL init*/
    lv_init();
    fbdev_init();
    lv_drv_init();

    /*Create Layout*/
    InitBackGround();
    InitLabelTopLeft();
    InitLabelBottomLeft();
    InitBtnWorkshopPwr();

    /*Handle LitlevGL tasks (tickless mode)*/
    int cnt = 0;
    while(1) {
        lv_timer_handler();
        usleep(5000);
        pthread_mutex_lock(&g_uiMutex);
        lv_label_set_text(g_labelBottomLeft, g_stateBarStr);
        pthread_mutex_unlock(&g_uiMutex);
    }

    return 0;
}

void GuiFrontPanelExit()
{
    printf("[%s] exit\n", APP_GUIFRONTPANEL);
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}

void lv_drv_init()
{
    /*A small buffer for LittlevGL to draw the screen's content*/
    static lv_color_t buf[DISP_BUF_SIZE];

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb   = fbdev_flush;
    disp_drv.hor_res    = LCD_H_RES;
    disp_drv.ver_res    = LCD_V_RES;
    disp_drv.sw_rotate    = 1;
    disp_drv.rotated      = LV_DISP_ROT_270;
    lv_disp_drv_register(&disp_drv);

    evdev_init();
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    /*This function will be called periodically (by the library) to get the mouse position and state*/
    indev_drv_1.read_cb = evdev_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);
}


void InitBackGround()
{
    static lv_style_t style;
    lv_style_init(&style);

    lv_style_set_bg_opa(&style, LV_OPA_COVER);
    lv_style_set_bg_color(&style, lv_color_make(0x0, 0x0, 0x0));

    lv_obj_t* bgk = lv_obj_create(lv_scr_act());
    lv_obj_add_style(bgk, &style, 0);
    lv_obj_set_size(bgk, LCD_V_RES, LCD_H_RES);
    lv_obj_center(bgk);
}

void InitLabelTopLeft()
{
    g_labelTopLeft = lv_label_create(lv_scr_act());
    lv_label_set_long_mode(g_labelTopLeft, LV_LABEL_LONG_WRAP);
    lv_label_set_recolor(g_labelTopLeft, true);
    lv_obj_set_width(g_labelTopLeft, LCD_V_RES);
    lv_obj_align(g_labelTopLeft, LV_ALIGN_TOP_LEFT, 0, 0);
    sprintf(strbuff, "Prj1UFront\n%s\nby masterraii@icloud.com", TIMESTAMPER_VER);
    lv_label_set_text(g_labelTopLeft, strbuff);
}

void InitLabelBottomLeft()
{
    g_labelBottomLeft = lv_label_create(lv_scr_act());
    lv_label_set_long_mode(g_labelBottomLeft, LV_LABEL_LONG_WRAP);
    lv_label_set_recolor(g_labelBottomLeft, true);
    lv_obj_set_width(g_labelBottomLeft, LCD_V_RES);
    lv_obj_align(g_labelBottomLeft, LV_ALIGN_BOTTOM_LEFT, 0, 0);
    sprintf(strbuff, "#00ff00 LINK_DOWN# -ms", TIMESTAMPER_VER);
    lv_label_set_text(g_labelBottomLeft, strbuff);
}

static void event_cb(lv_event_t * e)
{
    ToggleSwitch();
}

void InitBtnWorkshopPwr()
{
    g_btnWorkShopPwr = lv_btn_create(lv_scr_act());
    lv_obj_set_size(g_btnWorkShopPwr, 100, 100);
    lv_obj_align(g_btnWorkShopPwr, LV_ALIGN_TOP_RIGHT, 0, 0);
    lv_obj_add_event_cb(g_btnWorkShopPwr, event_cb, LV_EVENT_CLICKED, NULL);
}

void LogStateBar(const char *str, ...)
{
	pthread_mutex_lock(&g_uiMutex);
    va_list args;
    va_start(args, str);
    vsprintf(g_stateBarStr, str, args);
    va_end(args);
	pthread_mutex_unlock(&g_uiMutex);
}